﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XNAchievement.Achievements;

namespace XNAchievement.Achievements
{
    /// <summary>
    /// Represents a achievemet that is unlocked when ActionDone()
    /// is called x times in y sec. Use for achievements like "kill five
    /// enemys within 3 seconds" or "die 10 times in 2 minutes".
    /// Does no report progress.
    /// </summary>
    public class XInTimeAchievement : Achievement
    {
        /// <summary>
        /// When ActionDone() is called this often in TimeLimit the
        /// achievement is unlocked.
        /// </summary>
        public int UnlockValue { get; set; }

        /// <summary>
        /// When ActionDone() is called UnlockValue times in this
        /// time span the achievement is unlocked.
        /// </summary>
        public TimeSpan TimeLimit { get; set; }
        
        Queue<DateTime> actions = new Queue<DateTime>();

        /// <summary>
        /// Creates a locked achievements with the given internal name, using the given texture names.
        /// If no image is needed pass null for the name.
        /// </summary>
        public XInTimeAchievement(string internalName, string lockedTextureName, string unlockedTextureName)
            : base(internalName, lockedTextureName, unlockedTextureName)
        {
        }

        /// <summary>
        /// For internal use only.
        /// </summary>
        public XInTimeAchievement()
        {
        }

        /// <summary>
        /// Reports the achievement that the required
        /// action has been done "times" times.
        /// </summary>
        /// <param name="times">The times how often the action was done. Default: 1</param>
        public virtual void ActionDone(int times = 1)
        {
            //Clear exhausted actions in the queue
            DateTime now = DateTime.Now; //To avoid race contidions
            if (actions.Count > 0)
            {
                while (actions.Peek() <= now) //queue contains the exhaustion date!
                {
                    actions.Dequeue();
                }
            }

            //Add new actions to the queue
            for (int i = 0; i < times; i++)
            {
                actions.Enqueue(now + TimeLimit);
            }

            //Achievement unlocked?
            if (actions.Count >= UnlockValue)
                Unlock();
        }

        /// <summary>
        /// Resets the action counter to zero.
        /// </summary>
        public virtual void Reset()
        {
            actions.Clear();
        }
    }
}
